
//#include "stdafx.h"

//////////////////////////////////////////////////////////////////////////////////
//

#include "Cinematic.h"
#include "CinematicThread.h"
#include "CinematicCommand.h"
#include "FileSystem/IFileSystem.h"
#include "game.h"


using namespace irr;
using namespace io;
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
Cinematic::Cinematic(const char* fileName)
	:GameObject()
{			

	m_objectType = Object_Cinematic;

	m_CinematicThreads.clear();
	loadCinematic(fileName);
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
Cinematic::~Cinematic()
{
	for (u32 i = 0; i < m_CinematicThreads.size(); i ++)
	{
		if (m_CinematicThreads[i])
		{
			SAFE_DELETE( m_CinematicThreads[i] );
			m_CinematicThreads[i] = 0;
		}
	}
	m_CinematicThreads.clear();
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void Cinematic::SaveData(CWriteFile* stream)
{
	GameObject::SaveData(stream);

	stream->WriteU8 (m_isInCutscene);
	stream->WriteS32(m_state);
	for (u32 i = 0; i < m_CinematicThreads.size(); i ++)
		if (m_CinematicThreads[i])
			m_CinematicThreads[i]->SaveData(stream);
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void Cinematic::LoadData(CReadFile* stream)
{
	GameObject::LoadData(stream);

	m_isInCutscene = stream->ReadU8();
	m_state = (E_CINEMATIC_CODES)stream->ReadS32();
	for (u32 i = 0; i < m_CinematicThreads.size(); i ++)
		if (m_CinematicThreads[i])
			m_CinematicThreads[i]->LoadData(stream);
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------
void Cinematic::loadCinematic(const char* fileName)
{	
	CinematicThread* thread = 0;
	CinematicCommand* cinematicCmd = 0;
	SCinematicEvent* s = 0;

	IXMLReader* xml = getFileSystem()->createXMLReader(fileName);

	if (!xml)
	{
		DEBUG_OUT( "CCinematic::loadCinematic file NOT FOUND  %s !!!\n" ,  fileName);
		return;
	}
	
	while (xml->read())
	{
		switch(xml->getNodeType())
		{
			case EXN_ELEMENT:
			{
				if (!WCSCMP(WL("cinematicThread"), xml->getNodeName()))
				{
					thread = GL_NEW CinematicThread(); 
					thread->m_Type = xml->getAttributeValueAsInt(WL("type"));
					thread->m_ObjId = xml->getAttributeValueAsInt(WL("object"));

					int activeValue = xml->getAttributeValueAsInt(WL("active"));

					thread->m_isActive = (activeValue == 0 || activeValue == 1);
				}
				else if (!WCSCMP(WL("time"), xml->getNodeName()))
				{
					ASSERT(thread);
					s = GL_NEW SCinematicEvent();
					s->m_Time = MStoSEC(xml->getAttributeValueAsInt(WL("stamp")));
					s->m_CurrentStep = 0;
					
				} 
				else if (!WCSCMP(WL("command"), xml->getNodeName()))
				{
					cinematicCmd = GL_NEW CinematicCommand();
					cinematicCmd->m_id = xml->getAttributeValueAsInt(WL("id"));
					cinematicCmd->m_Name = xml->getAttributeValue(WL("name"));
				}								

				if (!WCSCMP(WL("attributes"), xml->getNodeName()))
				{
					if (cinematicCmd)
					{
						cinematicCmd->m_Attributes->read(xml, true);					
					}
				}								
			}
			break;

			case EXN_ELEMENT_END:
			{
				
				if (!WCSCMP(WL("time"), xml->getNodeName()))
				{
					//GX_ASSERT(thread);
					//push the list in the table 
					if (thread)
					{
						thread->m_CinematicEvent.push_back(s);
					}
					else
					{
						DEBUG_OUT("loadCinematic time ended but no thread !!!");
					}
				}

				if (!WCSCMP(WL("command"), xml->getNodeName()))
				{
					//push this command in the list 
					//GX_ASSERT(cinematicCmd);
					//GX_ASSERT(s);
					if (s && cinematicCmd)
					{
						s->m_CommandData.push_back(cinematicCmd);
						cinematicCmd = 0;
					}
					else
					{
						DEBUG_OUT("loadCinematic command ended but no Event or data !!!");
					}
				}
				
				if (!WCSCMP(WL("cinematicThread"), xml->getNodeName()))
				{
					//GX_ASSERT(thread);
					if (thread)
					{
						if (thread->m_isActive)
						{
							m_CinematicThreads.push_back(thread);
						}
						else
						{
							SAFE_DEL(thread);
						}
					}
					else
					{
						DEBUG_OUT("loadCinematic thread ended but no thread!!!");
					}
					thread = 0;
				}
				break;
			}
			
		}
	}

	xml->drop();
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
bool Cinematic::initCinematic()
{	
	m_state = E_CINEMATIC_STANDBY;
	m_isInCutscene = false;

	DEBUG_OUT("CCinematic::initCinematic %d\n" , GetID());
	
	bool bInited = true;

	for (int i = 0 ; i < m_CinematicThreads.size() ; i++ )
	{
		bInited &= m_CinematicThreads[i]->Init(m_objectID, this);
	}

	return bInited;
}

void Cinematic::setIsInCutscene (bool isInCutscene)
{
	m_isInCutscene = isInCutscene;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
void Cinematic::updateCinematic( float timeStep )
{
	if (m_CinematicThreads.size() == 0)
	{	
		m_state = E_CINEMATIC_EMPTY;
		return;
	}
	
	bool bFinished = true;

	for (int i = 0 ; i < m_CinematicThreads.size() ; i++ )
	{
		bFinished &= m_CinematicThreads[i]->Update(timeStep);
	}
	
	if (bFinished)
	{
		//DEBUG_OUT("CCinematic::updateCinematic %d Finished %d \n" , m_cinematicId , bFinished);
		m_state = E_CINEMATIC_FINISHED;
		return;
	}

	m_state = E_CINEMATIC_IN_PROGRESS;
}

void Cinematic::parseFinalAction ()
{
	for (int i = 0 ; i < m_CinematicThreads.size() ; i++ )
	{
		m_CinematicThreads[i]->doFinalAction ();
	}

	
	m_state = E_CINEMATIC_FINISHED;
}

float Cinematic::GetTime()
{
	if (m_CinematicThreads.size() == 0)
	{		
		return 0;
	}
	return m_CinematicThreads[0]->m_currentTime;
}

void Cinematic::reset()
{
	m_state = E_CINEMATIC_IN_PROGRESS;
	for (int i = 0 ; i < m_CinematicThreads.size() ; i++ )
	{
		m_CinematicThreads[i]->reset ();
	}
}
//--------------------------------------------------------------------------------------------------
//
//--------------------------------------------------------------------------------------------------